#include <jimix/IRQDispatcher.h>
#include <jimix/Process.h>
#include <signal.h>
#include <unistd.h>
#include "Tty.h"
#include "serial.h"

extern u32int _process;
extern SerialTty *serialTty1;
extern SerialTty *serialTty2;

bool ready_to_transmit(u16int port)
{
  u8int status = inb(port + 5);
  return (bool) (status & 0x20);
}

void serial_put(char c, u16int port)
{
  // Spin until the port is ready
  while (!ready_to_transmit(port))
    ;

  outb(port, c);
}

bool serial_is_input(u16int port)
{
  return inb(port+5)&1;
}

char serial_get_input(u16int port)
{
  return (char)inb(SERIAL_COM1);
}

void serial_handler(int sig)
{
  if (sig == 5)
  {
    while (serial_is_input(SERIAL_COM1))
    {
      char theChar = serial_get_input(SERIAL_COM1);
      // Convert '\r' to '\n' for UNIX style line endings.
      if (theChar == '\r')
        theChar = '\n';
      serialTty1->inputReceived(theChar);
      termios_t t;
      serialTty1->tcgetattr(&t);
      if (t.c_lflag & ECHO)
      {
        if ( (t.c_lflag & ECHONL) && 
              (theChar == '\n') )
        {
          serialTty1->write(theChar);
        }
        else if ( (t.c_lflag & ECHOE) &&
                   (theChar == (char)0x08) )
        {
//          serialTty1->backspace();
        }
        else if (theChar != '\n' && theChar != (char)0x08)
        {
          serialTty1->write(theChar);
        }
      }
    }
  }
}

void serial_init()
{
  signal(19, &serial_handler);
  u32int irqDispatcher = requestResource((char*)"IRQDispatcher");
  callResource(irqDispatcher, IRQDispatcher_IF::registerHandler, 4, getpid(), 19);
}
